package pe.com.sysaut.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;

import pe.com.sysaut.dao.GenericDao;


public class GenericDaoImpl implements GenericDao {

    private static final Logger log = Logger.getLogger(GenericDaoImpl.class);
    @Autowired
    private HibernateTemplate hibernateTemplate;

    @Override
	public void persist(Object entity) {
        log.debug("Guardando una instancia de: " + entity.getClass().getName());
        try {
            getHibernateTemplate().save(entity);
            log.debug("Guardado: ");
        } catch (RuntimeException re) {
            log.error("Fallo : ", re);
            throw re;
        } finally {
        	
        }
    }

    @Override
	public void update(Object entity) throws RuntimeException{
        log.debug("Actualizando una instancia de: " + entity.getClass().getName());
        try {
            getHibernateTemplate().update(entity);
            log.debug("Actualizado: ");
        } catch (RuntimeException re) {
            log.error("Fallo : ", re);
            throw re;
        } finally {
        	
        }
    }

    @Override
	public void persist(Object[] entities) {
        log.debug("Guardando una lista de instancias de: " + entities.getClass().getName());
        try {
            for (int i = 0; i < entities.length; i++) {
                persist(entities[i]);
            }
            log.debug("Guardado: ");
        } catch (RuntimeException re) {
            log.error("Fallo : ", re);
            throw re;
        } finally {
        	
        }
    }

    /**
     * Este metodo carga todos los objetos del tipo <b>entityClass</b>
     * @param <T>
     * @param entityClass
     * @return List
     */
    @Override
	@SuppressWarnings("unchecked")
	public <T> List<T> find(Class<T> entityClass) {
        log.debug("Buscando una lista de instancias");
        final List<T> entities;
        try {
            entities = getHibernateTemplate().loadAll(entityClass);
            log.debug("Listado exitoso de " + entityClass.getClass().getName());
        } catch (RuntimeException re) {
            log.error("Fallo el listado: ", re);
            throw re;
        } finally {
        	
        }
        return entities;
    }

    @Override
	@SuppressWarnings("unchecked")
	public <T> List<T> findByNamedQuery(String namedQuery) {
        log.debug("Guardando una lista de instancias");
        final List<T> entities;
        try {
            entities = getHibernateTemplate().findByNamedQuery(namedQuery);
            log.debug("Listado exitoso");
        } catch (RuntimeException re) {
            log.error("Fallo el listado: ", re);
            throw re;
        } finally {
        	
        }
        return entities;
    }

    /**
     * Este metodo retorna <b>null</b> en caso no encuentre el objeto
     * @param <T>
     * @param entityClass : La clase
     * @param id : El id del objeto, esto es el PK en la Base de Datos
     * @return El objeto encontrado por id.
     */
    @Override
	@SuppressWarnings("unchecked")
	public <T> T get(Class<T> entityClass, Serializable id) {
        log.debug("Cargado la clase " + entityClass.getClass().getName());
        final T entity;
        try {
            entity = (T) getHibernateTemplate().get(entityClass, id);
            log.debug("Carga exitosa de " + entityClass.getClass().getName());
        } catch (RuntimeException re) {
            log.error("Fallo el listado: ", re);
            throw re;
        } finally {
        	
        }
        return entity;
    }

    @Override
	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String hql, Object... params) {
        log.debug("Consulta hql : " + hql);
        final List<T> entities;
        try {
            entities = getHibernateTemplate().find(hql, params);
            log.debug("Consulta exitosa : " + hql);
        } catch (RuntimeException re) {
            log.error("Fallo : ", re);
            throw re;
        } finally {
        	
        }
        return entities;
    }

    @Override
	@SuppressWarnings("unchecked")
	public <T> List<T> findByHql(String hql) {
        log.debug("Consulta hql : " + hql);
        final List<T> entities;
        try {
            entities = getHibernateTemplate().find(hql);
            log.debug("Consulta exitosa : " + hql);
        } catch (RuntimeException re) {
            log.error("Fallo : ", re);
            throw re;
        } finally {
        	
        }
        return entities;
    }

    @Override
	public <T> void delete(Object entity) {
        log.debug("Eliminando : " + entity);
        try {
            getHibernateTemplate().delete(entity);
            log.debug("Eliminado exitosamente");
        } catch (RuntimeException re) {
            log.error("No se pudo eliminar : ", re);
            throw re;
        } finally {
        	
        }
    }

    @Override
	public void saveOrUpdate(Object entity) {
        log.debug("Guardando/Actualizando una instancia de: " + entity.getClass().getName());
        try {
            getHibernateTemplate().saveOrUpdate(entity);
            log.debug("Guardado/Actualizado");
        } catch (RuntimeException re) {
            log.error("Fallo : ");
            throw re;
        } finally {
        	
        }
    }

    @Override
	@SuppressWarnings("unchecked")
	public <T> List<T> findByParamNames(String hql, String[] paramNames, Object[] values) {
        final List<T> entities;
        try {
            entities = getHibernateTemplate().findByNamedParam(hql, paramNames, values);
        } catch (RuntimeException re) {
            throw re;
        } finally {
        	
        }
        return entities;
    }

    @Override
	public HibernateTemplate getHibernateTemplate() {
        return hibernateTemplate;
    }

    @Override
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }
}